#pragma once

#include <iostream>
#include <pthread.h>
#include <functional>
#include <string>
#include <cassert>
#include <memory>
#include <unistd.h>

typedef std::function<void *(void *)> func_t;

class Thread
{
public:
    const int num = 1024;

public:
    Thread()
    {
        char buf[num];
        snprintf(buf, sizeof(buf), "新线程-%d", _threadNum++);
        _name = buf;
    }

    // 线程函数要要求为    void*，void*(*)(void*)
    // void add()  add的类型为：void(*)()，add类型为函数指针
    // void *start_routine(void* args)，start_routine的类型void*(Thread::*)(void*)，这样多一个this指针，注意this指针的位置
    // void *start_routine(),  类型为void*(Thread::*)() ，也不符合，没有void*参数，且仍有this指针，
    // 可以认为，this指针实际是在函数指针类型前加了类类型和作用域限定符，即Thread::
    // 只能设置为静态的，因为静态成员函数没有this指针
    static void *start_routine(void *args)
    {
        //  _func(args);    // 没有this指针，无法访问非静态 成员

        Thread *this_ = (Thread *)args; // 我们传入的参数就是收到任务的线程类的指针，强转下就能用
        return this_->_func(this_->_args);
    }

    //这里构造函数只是创建线程，调用start才传递并开始执行线程函数
    void start(func_t func, void *args)
    {
        _func=func;
        _args=args;
        int n = pthread_create(&_tid, nullptr, start_routine, this);
        assert(n == 0);
        (void)n;
    }

    void join()
    {
        int n = pthread_join(_tid, nullptr);
        assert(n == 0); // 编译debug的方式发布时，assert语句存在，release方式发布就不存在了，n就成了定义但未使用，可能warning
        (void)n;
    }

    std::string threadName()
    {
        return _name;
    }

    ~Thread()
    {
    }

private:
    std::string _name;
    void *_args;
    pthread_t _tid;
    func_t _func;

    static int _threadNum;
};

int Thread::_threadNum = 1;